use serde::{Deserialize, Serialize};
use serde_json::{json, from_str};
use sqlx::postgres::{PgPool};
use axum::{
    extract::Extension,
    Json,
};
use crate::middleware::{
    error::Error,
    response::{MyResponseStruct, MyResponse}, https::{read_get_body, MyHttps}
};

#[derive(Serialize,Deserialize,Clone,Debug)]
pub struct Userinfo {
    avatar_url: String,
    nick_name:String,
    city: String,
    province:String,
    country:String,
    gender: i64,
    language:String,
}
#[derive(Serialize,Deserialize,Clone,Debug)]
pub struct Logininfo {
    appid: String,
    secret:String,
    code: String,
    userinfo:Userinfo,
}
#[derive(Serialize,Deserialize,Clone)]
pub struct LoginStatus {
    openid:String,
    session_key:String,
}

//登录
pub async fn login(
    Json(payload): Json<Logininfo>,
    Extension(pool): Extension<PgPool>,
    Extension(client): Extension<MyHttps>,
) -> Result<Json<MyResponseStruct>, Error> {
    let uri =format!("https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code",
        payload.appid,payload.secret,payload.code).parse()?;
    //body 转化字符串
    let res = read_get_body(&client,uri).await?;
    // 反序列化
    let login_status =from_str::<LoginStatus>(&res)?;

    let option = sqlx::query!("SELECT  FROM users WHERE openid=$1",payload.appid)
        .fetch_optional(&pool).await?;

    match option {
        //有判断登录是否过期
        Some(_) =>is_login(&login_status, &pool).await?,
        //未注册
        None =>register(&login_status, &payload.userinfo, &pool).await?,
    }
    Ok(MyResponse::Success(json!("登录成功")).into())
} 


//判断登录是否过期
pub async  fn is_login(login_status :&LoginStatus,pool:&PgPool) ->Result<(),Error>{
    let _session_key =  sqlx::query!("SELECT session_key FROM users WHERE openid=$1",login_status.openid)
        .fetch_one(pool).await?.session_key;

    match login_status.session_key.clone()  {
        //登录未过期
        _session_key=>(),
        // session_key 过期 更新 session_key
        _=>{
            sqlx::query!("UPDATE users SET session_key=$1  WHERE openid=$2",login_status.session_key,login_status.openid)
                .execute(pool).await?.rows_affected();
        }
    }
    Ok(())
}

//注册新用户
pub async fn register (login_status :&LoginStatus, userinfo: &Userinfo, pool:&PgPool) ->Result<(),Error> {
    sqlx::query!("INSERT  INTO users (openid,session_key,avatar_url,nick_name,city,province,country,gender,language) 
        VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9) RETURNING openid",
        login_status.openid,
        login_status.session_key, 
        userinfo.avatar_url,
        userinfo.nick_name,
        userinfo.city,
        userinfo.province,
        userinfo.country,
        userinfo.gender,
        userinfo.language
    )
    .fetch_one(pool).await?;
    Ok(())
}

//查询所有用户
#[derive(Serialize,Deserialize,Clone,Debug)]
struct  User {
    avatar_url:String,
    nick_name :String,

}
pub async fn get_all_users(Extension(pool): Extension<PgPool>)-> Result<Json<MyResponseStruct>, Error>{
    let res:Vec<User> = sqlx::query!("SELECT * FROM users")
    .fetch_all(&pool).await?.into_iter().map(|x| User{ avatar_url: x.avatar_url, nick_name: x.nick_name }).collect();

    Ok(MyResponse::Success(json!(res)).into())
}





